﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using DependencyAnalysis.DataModel;
using DependencyAnalysis.Internal;
using DependencyAnalysis.Serialization;

namespace DependencyAnalysis
{
    /// <summary>
    /// 
    /// </summary>
    public class Setup : MarshalByRefObject
    {
        public IDependencyModel Model { get; private set; }
        public IAnalyzer Analyzer { get; private set; }
        public IVerifier Verifier { get; private set; }
        public Metrics Metrics { get; private set; }

        private Setup()
        {
        }

        /// <summary>
        /// Create a test setup with Verification and Metrics.
        /// </summary>
        /// <returns></returns>
        public static Setup BuildStandardSetup()
        {
            var dependencyModel = new DependencyModel();
            return new Setup
                {
                    Model = dependencyModel,
                    Analyzer = new Analyzer(dependencyModel),
                    Verifier = new Verifier(dependencyModel),
                    Metrics = new MetricsImplementation(dependencyModel)
                };
        }

        /// <summary>
        /// Create a test setup with Verification and Metrics given an existing
        /// data model.
        /// </summary>
        /// <returns></returns>
        public static Setup BuildSetupFromModel(IDependencyModel dependencyModel)
        {
            return new Setup
            {
                Model = dependencyModel,
                Analyzer = new Analyzer(dependencyModel),
                Verifier = new Verifier(dependencyModel),
                Metrics = new MetricsImplementation(dependencyModel)
            };
        }
        /// <summary>
        /// Analyze the given modules for dependencies and add them to the current
        /// dependency model.
        /// </summary>
        /// <param name="projectModuleFiles"></param>
        public void StartAnalysis(IEnumerable<string> projectModuleFiles)
        {
            Analyzer.BuildDependencies(projectModuleFiles);
        }

        /// <summary>
        /// Analyze the given modules for dependencies and add them to the current
        /// dependency model.
        /// </summary>
        /// <param name="projectModules"></param>
        public void StartAnalysis(IEnumerable<Assembly> projectModules)
        {
            Analyzer.BuildDependencies(projectModules);
        }

        /// <summary>
        /// XML reports will give you an overview on a certain aspect of your project. This can be for
        /// example a complete analysis of code metrics or code duplicates.
        /// </summary>
        public void CreateReportXml<TReport>(string reportFilePath, string xslTransformReference) where TReport : IReport, new()
        {
            var serializer = new XmlSerializer(typeof(XmlSerializableExpandoObject), new XmlRootAttribute("Report"));
            using (var writer = new XmlTextWriter(reportFilePath, Encoding.UTF8))
            {
                IReport reportBuilder = new TReport { Setup = this };
                dynamic report = reportBuilder.FetchReport<XmlSerializableExpandoObject>();
                report.CreationDate = DateTime.Now;
                    writer.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
                if (!string.IsNullOrWhiteSpace(xslTransformReference))
                {
                    writer.WriteProcessingInstruction("xml-stylesheet",
                                                      "type=\"text/xsl\" href=\"" + xslTransformReference + "\"");
                }
                serializer.Serialize(writer, report);
            }
        }
    }
}
